from gunicorn.app.base import BaseApplication

from .views import create_app


class PublicPrivateHandler:
    def __init__(self, public_handler, private_handler, private_port):
        self.public_handler = public_handler
        self.private_handler = private_handler
        self.private_port = private_port

    def __call__(self, environ, start_response):
        server_port = str(environ.get('SERVER_PORT'))
        if server_port == str(self.private_port):
            return self.private_handler(environ, start_response)
        else:
            return self.public_handler(environ, start_response)


class TinyopsApplication(BaseApplication):
    def __init__(self, handler_factory, config, **kwargs):
        self._config = config
        webui = self._config.webui
        if webui.port == webui.webhook_port:
            self.handler = handler_factory(self._config, **kwargs)
        else:
            self.handler = PublicPrivateHandler(
                public_handler=handler_factory(
                    self._config, only_webhook=True, **kwargs),
                private_handler=handler_factory(self._config, **kwargs),
                private_port=webui.port,
            )
        super(TinyopsApplication, self).__init__()

    def load_config(self):
        webui = self._config.webui
        ports = set([webui.port, webui.webhook_port])
        self.cfg.set('bind', [f'{webui.host}:{port}' for port in ports])
        self.cfg.set('threads', webui.threads)
        self.cfg.set('backlog', webui.threads)
        self.cfg.set('forwarded_allow_ips', '*')
        self.cfg.set('proxy_allow_ips', '*')
        self.cfg.set('accesslog', webui.access_logfile)
        self.cfg.set('errorlog', webui.error_logfile)
        loglevel = 'debug' if self._config.debug else 'info'
        self.cfg.set('loglevel', loglevel)

    def load(self):
        return self.handler


class WebUI:

    def __init__(self, config, **kwargs):
        self.config = config
        self.app = TinyopsApplication(create_app, config, **kwargs)

    def main(self):
        self.app.run()
